package com.csx.data.orm.jpa.batch.controller;

import com.csx.data.orm.jpa.base.entity.User;
import com.csx.data.orm.jpa.batch.service.UserBatchService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.ArrayList;
import java.util.List;

@RequestMapping("/jpa/batch")
@RestController
public class UserBatchController {

    private final List<User> mockDataList = new ArrayList<>();

    @Autowired
    private UserBatchService userBatchService;

    /**
     * 情况1: 使用 saveAll 方法做伪批量
     * 测试结果: 执行了约 43s
     */
    @PostMapping("/batchInsertWithSaveAll/{quantity}")
    public List<User> batchInsertWithSaveAll(@PathVariable("quantity") Integer quantity) {
        // 模拟 quantity 数量的数据插入
        List<User> users = mockData(quantity);
        return userBatchService.saveAll(users);
    }

    /**
     * 情况2: 使用entityManager 方法做批量插入
     * 测试结果: 执行了约60s
     */
    @PostMapping("/batchInsertWithEntityManager/{quantity}")
    public List<User> batchInsertWithEntityManager(@PathVariable("quantity") Integer quantity) {
        // 模拟 quantity 数量的数据插入
        List<User> users = mockData(quantity);
        return userBatchService.batchExecute(users);
    }

    /**
     * 情况2-2: 使用entityManager 方法做批量插入
     * 测试结果: 失败。 需要进一步优化
     */
    @PostMapping("/batchInsertWithEntityManager2/{quantity}")
    public String batchInsertWithEntityManager2(@PathVariable("quantity") Integer quantity) {
        // 模拟 quantity 数量的数据插入
        List<User> users = mockData(quantity);
        userBatchService.batchExecuteWithEntityManager(users);
        return "success";
    }
    /**
     * 情况3: 使用entityManager 方法做批量插入,同时使用多线程
     * 测试结果: 10个线程将近40s
     */
    @PostMapping("/batchInsertWithEntityManagerAndThreadPool/{quantity}")
    public List<User> batchInsertWithEntityManagerAndThreadPool(@PathVariable("quantity") Integer quantity) {
        // 模拟 quantity 数量的数据插入
        List<User> users = mockData(quantity);
        return userBatchService.batchExecuteWithThreadPool(users);
    }

    /**
     * 情况4: 自己拼接 sql，利用 原生jdbcTemplate执行
     * 测试结果: 1s左右,执行了 26个事务,每个事务插入200行数据
     */
    @PostMapping("/batchInsertWithJdbcTemplate/{quantity}")
    public String batchInsertWithJdbcTemplate(@PathVariable("quantity") Integer quantity) {
        // 模拟 quantity 数量的数据插入
        List<User> users = mockData(quantity);
        userBatchService.batchInsertWithJdbcTemplate(users);
        return "success";
    }

    private List<User> mockData(Integer quantity) {

        if(mockDataList.size() == quantity) {
            return mockDataList;
        }

        for (int i = 0; i < quantity; i++) {
            User user = new User();
            user.setFirstName("mock_first_name " + i);
            user.setLastName("mock_last_name " + i);
            user.setCity("chengdu");
            user.setAge(18);

            mockDataList.add(user);
        }

        return mockDataList;
    }
}
